/**
 *Copyright (c) 2024 watereyes
 * workflow is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.workflow.systemManag.service.impl;

import com.google.common.base.Splitter;
import com.koron.workflow.common.util.WorkflowUtil;
import com.koron.workflow.systemManag.bean.EnumItemBean;
import com.koron.workflow.systemManag.bean.EnumQueryBean;
import com.koron.workflow.systemManag.bean.EnumUpdateBean;
import com.koron.workflow.systemManag.mapper.EnumMapper;
import com.koron.workflow.systemManag.service.EnumService;
import com.koron.workflow.common.bean.PageBean;
import com.koron.workflow.common.bean.StaffBean;
import com.koron.workflow.common.util.BusinessCode;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.swan.bean.MessageBean;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class EnumServiceImpl implements EnumService {
    private static final Logger logger = LoggerFactory.getLogger(EnumServiceImpl.class);

    @TaskAnnotation("queryForList")
    @Override
    public PageBean queryForList(SessionFactory factory, String code, String name, Integer page, Integer pageSize) {
        EnumMapper mapper = factory.getMapper(EnumMapper.class);
        List<Map> list = mapper.queryForList(code, name, page, pageSize);
        Integer total = null;
        if (page != null || pageSize != null) {
            total = mapper.countQueryForList(code, name);
        }
        return new PageBean<>(list, total);
    }

    @TaskAnnotation("queryForObject")
    @Override
    public EnumQueryBean queryForObject(SessionFactory factory, String code) {
        List<Map> list = factory.getMapper(EnumMapper.class).queryEnumMsgs(code);
        EnumQueryBean bean = null;
        if (list != null && list.size() > 0) {
            bean = new EnumQueryBean();
            bean.setCode(list.get(0).get("code").toString());
            bean.setName(Optional.of(list.get(0).get("name")).orElse("").toString());
            List<EnumItemBean> enumItemBeans = new LinkedList<>();
            EnumItemBean enumItemBean;
            for (Map<String, String> map : list) {
                enumItemBean = new EnumItemBean();
                enumItemBean.setKey(map.get("key"));
                enumItemBean.setValue(map.get("value"));
                if (!StringUtils.isEmpty(map.get("sn"))) {
                    enumItemBean.setSn(Integer.parseInt(map.get("sn")));
                }
                enumItemBeans.add(enumItemBean);
            }
            bean.setItemBeans(enumItemBeans);
        }
        return bean;
    }

    @TaskAnnotation("save")
    @Override
    public MessageBean save(SessionFactory factory, StaffBean user, EnumQueryBean bean) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        try {
            if (StringUtils.isEmpty(bean.getCode())) {
                msg.setCode(BusinessCode.EMPTY_PARAM.getCode());
                msg.setDescription("字典组编号不能为空");
                return msg;
            }
            EnumMapper mapper = factory.getMapper(EnumMapper.class);
            // 验证当前 字典组编号 是否已经存在
            if (mapper.checkoutCode(bean.getCode()) > 0) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("该字典组编号已经存在");
                return msg;
            }
            String userCode = user.getCode();
            String userName = user.getName();
            Date date = new Date();
            List<EnumItemBean> enumItemBeans = bean.getItemBeans();
            List<EnumUpdateBean> insertBeans = new LinkedList<>();
            EnumUpdateBean enumUpdateBean;
            if (enumItemBeans != null && enumItemBeans.size() > 0) {
                // 验证判断当前字典项key是否重复
                if (enumItemBeans.stream().map(enumItemBean -> enumItemBean.getKey()).distinct().count() != enumItemBeans.size()) {
                    factory.close(false);
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("当前字典组中,字典名称存在重复项");
                    return msg;
                }
                for (EnumItemBean item : enumItemBeans) {
                    if (StringUtils.isEmpty(item.getKey()) || StringUtils.isEmpty(item.getValue())) {
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("数据字典项名称和值不能为空");
                        return msg;
                    }
                    if (item.getKey().length() > 50){
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("数据字典项名称最多输入50个字符");
                        return msg;
                    }
                    if (item.getValue().length() > 50){
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("数据字典项值最多输入50个字符");
                        return msg;
                    }
                    if (item.getSn() != null && (item.getSn() < 0 || item.getSn() > 100)){
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("数据字典项排序号为0-100之间");
                        return msg;
                    }
                    enumUpdateBean = new EnumUpdateBean();
                    enumUpdateBean.setKey(item.getKey());
                    enumUpdateBean.setValue(item.getValue());
                    enumUpdateBean.setSn(item.getSn());
                    insertBeans.add(enumUpdateBean);
                }
            } else {
                enumUpdateBean = new EnumUpdateBean();
                insertBeans.add(enumUpdateBean);
            }
            for (EnumUpdateBean updateBean : insertBeans) {
                updateBean.setId(WorkflowUtil.getObjectId());
                updateBean.setCode(bean.getCode());
                updateBean.setName(bean.getName());
                updateBean.setCreateUser(userCode);
                updateBean.setCreateUserName(userName);
                updateBean.setCreateTime(date);
                updateBean.setLastUpdateUser(userCode);
                updateBean.setLastUpdateUserName(userName);
                updateBean.setLastUpdateTime(date);
            }
            if (mapper.insert(insertBeans) != insertBeans.size()) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription(BusinessCode.FAILURE.getDescription());
                return msg;
            }
        } catch (Exception e) {
            factory.close(false);
            logger.error("数据字典保存失败", e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @TaskAnnotation("update")
    @Override
    public MessageBean update(SessionFactory factory, StaffBean user, String oldCode, EnumQueryBean bean) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        try {
            if (StringUtils.isEmpty(bean.getCode())) {
                msg.setCode(BusinessCode.EMPTY_PARAM.getCode());
                msg.setDescription("字典组编号不能为空");
                return msg;
            }
            if (StringUtils.isEmpty(oldCode)) {
                msg.setCode(BusinessCode.EMPTY_PARAM.getCode());
                msg.setDescription("没有获取当前业务唯一标识");
                return msg;
            }
            EnumMapper mapper = factory.getMapper(EnumMapper.class);
            // 验证当前 字典组编号 是否已经存在
            if (!oldCode.equals(bean.getCode()) && mapper.checkoutCode(bean.getCode()) > 0) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription("该字典组编号已经存在");
                return msg;
            }
            String userCode = user.getCode();
            String userName = user.getName();
            Date date = new Date();
            List<EnumItemBean> enumItemBeans = bean.getItemBeans();
            List<EnumUpdateBean> insertBeans = new LinkedList<>();
            EnumUpdateBean enumUpdateBean;
            if (enumItemBeans != null && enumItemBeans.size() > 0) {
                // 验证判断当前字典项key是否重复
                if (enumItemBeans.stream().map(enumItemBean -> enumItemBean.getKey()).distinct().count() != enumItemBeans.size()) {
                    factory.close(false);
                    msg.setCode(BusinessCode.FAILURE.getCode());
                    msg.setDescription("当前字典组中,字典名称存在重复项");
                    return msg;
                }
                for (EnumItemBean item : enumItemBeans) {
                    if (StringUtils.isEmpty(item.getKey()) || StringUtils.isEmpty(item.getValue())) {
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("数据字典项名称和值不能为空");
                        return msg;
                    }
                    if (item.getKey().length() > 50){
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("数据字典项名称最多输入50个字符");
                        return msg;
                    }
                    if (item.getValue().length() > 50){
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("数据字典项值最多输入50个字符");
                        return msg;
                    }
                    if (item.getSn() != null && (item.getSn() < 0 || item.getSn() > 100)){
                        factory.close(false);
                        msg.setCode(BusinessCode.FAILURE.getCode());
                        msg.setDescription("数据字典项排序号为0-100之间");
                        return msg;
                    }
                    enumUpdateBean = new EnumUpdateBean();
                    enumUpdateBean.setKey(item.getKey());
                    enumUpdateBean.setValue(item.getValue());
                    enumUpdateBean.setSn(item.getSn());
                    insertBeans.add(enumUpdateBean);
                }
            } else {
                enumUpdateBean = new EnumUpdateBean();
                insertBeans.add(enumUpdateBean);
            }
            for (EnumUpdateBean updateBean : insertBeans) {
                updateBean.setId(WorkflowUtil.getObjectId());
                updateBean.setCode(bean.getCode());
                updateBean.setName(bean.getName());
                updateBean.setCreateUser(userCode);
                updateBean.setCreateUserName(userName);
                updateBean.setCreateTime(date);
                updateBean.setLastUpdateUser(userCode);
                updateBean.setLastUpdateUserName(userName);
                updateBean.setLastUpdateTime(date);
            }
            // 删除历史code的相关数据
            mapper.delete(oldCode);
            if (mapper.insert(insertBeans) != insertBeans.size()) {
                factory.close(false);
                msg.setCode(BusinessCode.FAILURE.getCode());
                msg.setDescription(BusinessCode.FAILURE.getDescription());
                return msg;
            }
        } catch (Exception e) {
            factory.close(false);
            logger.error("数据字典修改失败", e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @TaskAnnotation("delete")
    @Override
    public MessageBean delete(SessionFactory factory, String code) {
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        try {
            factory.getMapper(EnumMapper.class).delete(code);
        } catch (Exception e) {
            factory.close(false);
            logger.error("数据字典删除失败", e);
            msg.setCode(BusinessCode.EXCEPTION.getCode());
            msg.setDescription(BusinessCode.EXCEPTION.getDescription());
        }
        return msg;
    }

    @TaskAnnotation("querySelectByCode")
    @Override
    public List<Map> querySelectByCode(SessionFactory factory, String code, String filterKeys) {
        List<String> keys = null;
        if (!StringUtils.isEmpty(filterKeys)) {
            keys = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(filterKeys);
        }
        return factory.getMapper(EnumMapper.class).querySelectByCode(code, keys);
    }

    @TaskAnnotation("queryAllEnum")
    @Override
    public List<Map> queryAllEnum(SessionFactory factory) {
        List<Map> list = factory.getMapper(EnumMapper.class).queryAllEnum();
        List<Map> enums = new LinkedList<>();
        if (list != null && list.size() > 0) {
            List<String> codes = list.stream().map(map -> map.get("code").toString()).distinct().collect(Collectors.toList());
            codes.stream().forEach(code -> {
                Map enumItem = new HashMap();
                enumItem.put("code", code);
                List<Map> items = new LinkedList<>();
                list.stream().forEach(map1 -> {
                    if (code.equals(map1.get("code").toString())) {
                        items.add(map1);
                    }
                });
                enumItem.put("items", items);
                enums.add(enumItem);
            });
        }
        return enums;
    }
}
